Skip to content

[python][torch] Add batch-first streaming datasets - #9365

Merged
JingsongLi merged 8 commits into
apache:masterfrom
XiaoHongbo-Hope:codex/pypaimon-torch-batches
Aug 27, 2026
Merged

[python][torch] Add batch-first streaming datasets#9365
JingsongLi merged 8 commits into
apache:masterfrom
XiaoHongbo-Hope:codex/pypaimon-torch-batches

Conversation

@XiaoHongbo-Hope

@XiaoHongbo-Hope XiaoHongbo-Hope commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Purpose

Avoid per-row Python conversion by allowing PyPaimon Torch streaming datasets to yield PyArrow RecordBatch objects or dictionaries of Torch tensors.

  • batch_format="row" remains the default; "pyarrow" and "torch" enable batch streaming.
  • batch_size=None preserves reader batches; otherwise batches are combined or sliced.
  • The default converter supports non-null numeric, boolean, and numeric fixed-size-list columns. Other types can use to_tensor_fn.
  • Use DataLoader(batch_size=None) to avoid a second batching step.

Batch formats use one reader per DataLoader worker and require prefetch_concurrency=1, because Python producer threads cannot reliably cancel a reader blocked in I/O. A non-binding global limit preserves DataLoader worker parallelism when validated merged row counts, or physical row-count upper bounds, prove that all rows fit.

Related implementations

LanceDataset also streams Arrow batches and provides batch_size, to_tensor_fn, and native batch_readahead. PyIceberg provides to_arrow_batch_reader(), but not a PyTorch Dataset or Tensor conversion layer.

Tests

  • Torch tests: 25 passed
  • Binding and non-binding multi-worker limits, merged-row limits, and Arrow offset-overflow regressions
  • Flake8, Python 3.6 py_compile, and git diff --check

@XiaoHongbo-Hope
XiaoHongbo-Hope marked this pull request as draft August 23, 2026 15:53
@XiaoHongbo-Hope
XiaoHongbo-Hope marked this pull request as ready for review August 26, 2026 14:02
return True
total_rows = 0
for split in self.splits:
row_count = getattr(split, "row_count", None)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Use merged row counts before collapsing DataLoader workers

Split.row_count is the sum of physical file rows, so it can substantially exceed the logical output for deletion-vector and Data Evolution splits. For example, if two splits each have 10 physical rows but 4 merged rows and the limit is 8, the limit is non-binding; this code nevertheless totals 20 and routes every split to worker 0, unnecessarily regressing row, shuffle, and batch streaming from multi-worker to single-worker execution. TableRead._limit_covers_all_splits already uses split.merged_row_count() for the same proof. Please prefer a validated merged_row_count() when it is available, fall back conservatively when it is unknown, and add a non-binding test where physical and merged counts differ.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in cc695c0. The worker-limit proof now prefers merged_row_count() only when it is a valid nonnegative count no larger than the physical row count; otherwise it falls back to the physical upper bound. The regression covers 20 physical rows, 8 merged rows, and limit=8 retaining both workers.

@JingsongLi JingsongLi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@JingsongLi
JingsongLi merged commit 08337b6 into apache:master Aug 27, 2026
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants